package com.ztic;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.*;
import com.sun.jna.win32.StdCallLibrary;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

//定义Em9118类，是对Em9118.dll输出函数的二次封装，并定义了一些操作函数
//用户直接使用Em9118类的实例
//Em9118.dll放到用户Java主程序目录下、%System32%目录下、或者其他%Path%变量指明的目录下
public class Em9118 {

    //region Em9118.dll接口声明
    public interface IEm9118 extends StdCallLibrary {
        public static IEm9118 INSTANCE = (IEm9118)
                Native.load("EM9118.dll", IEm9118.class);

        //--------------------------------设备管理----------------------------------
        //创建设备
        long EM9118_DeviceCreate();
        //关闭设备
        void EM9118_DeviceClose(long pDev);
        //命令连接
        int EM9118_CmdConnect(long pDev, Pointer strIP, int ipBC, int port, int timeout);
        //数据连接
        int EM9118_DataConnect(long pDev, int dataPort, int timeout);
        //关闭数据连接
        void EM9118_DataClose(long pDev,int timeout);
        //关闭命令连接
        void EM9118_CmdClose(long pDev,int timeout);

        int EM9118_DataConnectEx( long hDevice, int dataPort, int timeOutMS  );

        int EM9118_SetDhcp( long hDevice, byte isDhcp, byte delayTimeS, byte bcRoute, int timeOutMS  );

        int EM9118_GetDhcp( long hDevice, Pointer isDhcp, Pointer delayTimeS,Pointer bcRoute, int timeOutMS  );

        //---------------------------------------PWM部分--------------------------------------------
        //功能：设置PWM频率和占空比
        //输入参量：
        //chNo-通道号，从1开始。
        //freq-设定频率
        //duty-设定占空比
        //timeout-溢出时间
        //输出参量：
        //realFreq-实际频率
        //realDuty-实际占空比
        //返回值
        //0-无错误
        int EM9118_PwmSetPulse(long pDev, int chNo, double freq, double duty, DoubleByReference realFreq, DoubleByReference realDuty, int timeout);
        //设定所有通道的PWM输出开始或者停止
        int EM9118_PwmStartAll(long pDev, byte[] startOrStop,byte[] is90, int timeout);
        //在指定脉冲输出个数的情况下，判断PWM输出是否完成
        int EM9118_PwmIsOver(long pDev, byte[] isOver,int timeout);
        //设定输出脉冲个数
        int EM9118_PwmSetCount(long pDev, int chNo,int setCount,int timeout);


        //---------------------------------------编码器部分----------------------------------
        //编码器清零
        int EM9118_EcClear(long pDev, int[] chClear,int timeout);
        //读回所有通道的编码器值
        int EM9118_EcReadCodeAll(long pDev, int[] encoderAB, int[] encoderZ, int timeout);
        //设置编码器通道是否进入FIFO
        int EM9118_EcChIsInFifo(long pDev, int[] isInFifo,int timeout);

        int EM9118_EcChGetCode( long hDevice, int chInx, int bytesCount, ByteByReference codeBuffer, IntByReference ecCode, IntByReference ecCodeCount );


        //----------------------------------------IO采集部分----------------------------------------
        //设置DO管脚功能
        int EM9118_DoSetMode(long pDev, byte doMode1,byte doMode2,int timeout);
        //设置所有通道开关量值
        int EM9118_DoAll(long pDev, byte[] oStatus, int timeout);
        //得到所有通道开关量值
        int EM9118_DiAll(long pDev, byte[] iStatus, int timeout);


        //----------------------------------------CT计数器/测频部分----------------------------------------
        //设置所有路计数器的工作方式
        int EM9118_CtSetModeAll(long pDev, byte[] ctMode,  int timeout);

        //设置指定通道的计数器测频基准脉冲周期，以毫秒为单位
        int EM9118_CtSetFreqBase(long pDev, int chNo, double freqBase_ms, DoubleByReference real_ms, int timeout);

        //读取所有路计数器的原码值
        int EM9118_CtReadCodeAll(long pDev, int[] ctCode, int timeout);

        //将计数器一批原码值转换成物理值，计数时转换结果就是计数值，测频是转换结果是频率值
        int EM9118_CtChBatchCodeToValue(long pDev, int chNo, int[] pCode, int codeCount, double[] ctValue);

        //指定通道计数器清零(本函数只有在计数方式下才有意义，因此执行后会将相应通道设置为计数工作方式)
        int EM9118_CtClear(long pDev, int chNo, int timeout);

        //设置计数器通道是否进入FIFO
        int EM9118_CtChIsInFifo(long pDev, int[] isInFifo,int timeout);

        int EM9118_CtChGetCode( long hDevice, int chInx, int bytesCount, ByteByReference codeBuffer, IntByReference ctCode, IntByReference ctCodeCount );

        int EM9118_CtSetFilter( long hDevice, short filterInx, int timeOutMS  );

        int EM9118_CtGetFilter( long hDevice, ShortByReference filterInx, int timeOutMS  );



        //--------------------------------------------------------AD采集相关----------------------------------------------------------
        int EM9118_AdChIsInFifo( long hDevice, int[] isInFifo, int timeOutMS  );

        int EM9118_AdSetRange( long hDevice, int rangeInx, int timeOutMS  );

        int EM9118_HcSetGroupFreq( long hDevice,  double groupFreq, int timeOutMS  );

        int EM9118_GetFifoAdChCount( long hDevice );

        int EM9118_GetFifoCtChCount( long hDevice );

        int EM9118_GetFifoEcChCount( long hDevice );

        int EM9118_GetFifoGroupByteCount( long hDevice, IntByReference byteCount );

//------------------------------------------------------------------------------------------------------------------------------

        int EM9118_AdReadZeroFullCode( long hDevice, short[] zeroCode, short[] fullCode, int timeOutMS  );

        int EM9118_AdWriteZero( long hDevice, int chNo, short zeroCode, int timeOutMS  );

        int EM9118_AdWriteFull( long hDevice, int chNo, short fullCode, int timeOutMS  );
//------------------------------------------------------------------------------------------------------------------------------

        int EM9118_HcSetTriCount( long hDevice, int triCount, int timeOutMS  );

        int EM9106_HcStart( long hDevice, int clkSrc, int triSrc, int edgeOrLevel, int upOrDown, int timeOutMS  );

        int EM9118_HcStart( long hDevice, int clkSrc, int triSrc, int edgeOrLevel, int upOrDown, int timeOutMS  );

        int EM9118_HcStop( long hDevice, int timeOutMS  );


        int EM9118_HcSetTimestamp( long hDevice, byte enBit, int timeOutMS  );

        int EM9118_HcGetTimestamp(long hDevice, ByteByReference enBit, int timeOutMS  );

        int EM9118_HcGetMaxGroupCnt( long hDevice, int triSrc, ShortByReference maxGroupCnt );

        int EM9118_HcGetGcFromBc( long hDevice, int triSrc, short bytesCnt, ShortByReference groupCnt, ShortByReference realBytesCnt );

        int EM9118_HcSetBcInPack( long hDevice, int triSrc, short maxBc, ShortByReference groupCnt, ShortByReference realBytesCnt, int timeOutMS);

        int EM9118_HcSetGroupCnt( long hDevice, short groupCnt, int timeOutMS  );

        int EM9118_HcGetGroupCnt( long hDevice, int triSrc, ShortByReference groupCnt, ShortByReference packBytesCnt, int timeOutMS  );

        int EM9118_HcReadData( long hDevice, int byteCount, byte[] codeBuffer, IntByReference realByteCount, int timeOutMS  );

        int EM9118_HcReadDataAll( long hDevice, int byteCount, byte[] CodeBuffer, IntByReference realByteCount, int timeOutMS  );

        int EM9118_HcTSReadData(long hDevice, int bytesCount, ByteByReference CodeBuffer, IntByReference realByteCount, LongByReference timestampUS, int timeOutMS  );

        int EM9118_AdChGetCode( long hDevice, int chInx, int bytesCount, byte[] codeBuffer, short[] adCode, IntByReference adCodeCount );

        int EM9118_AdChBatchCodeToValue( long hDevice, int chNo, short[] pCode, int codeCount, double[] adValue );


        //------------------------------------------------------------------------------------------------------------------------------
        int EM9118_AdChSetZeroFullValue( long hDevice, int chNo, double zeroValue, double fullValue );

        int EM9118_AdReadAllCodeOnce( long hDevice, short[] adCode, int timeOutMS  );

        int EM9118_AdChCodeToValue( long hDevice, int chNo, short iCode, DoubleByReference adValue );

        int EM9106_CmdGetInFifo( long hDevice, IntByReference adInFifo, IntByReference ctInFifo, IntByReference ecInFifo, IntByReference diInFifo, int timeOutMS  );

        int EM9118_CmdGetInFifo( long hDevice, Pointer adInFifo, Pointer ctInFifo, Pointer ecInFifo, IntByReference diInFifo, int timeOutMS  );

        int EM9118_CmdGetFreq( long hDevice, IntByReference hcFreq, int timeOutMS  );

//------------------------------------------------------------------------------------------------------------------------------



//-----------------------数据文件存储相关---------------------------------------------------------------------------

        int EM9118_CSVOpen( long hDevice, ByteByReference dirPath, int pathLen );

        int EM9118_CSVClose( long hDevice );

        int EM9118_CSVWriteValue( long hDevice, ByteByReference pCode, int codeBC );

        int EM9118_DFWOpen( long hDevice, ByteByReference dirPath, int pathLen );

        int EM9118_DFWClose( long hDevice );

        int EM9118_DFWrite( long hDevice, ByteByReference pCode, int codeBC );

        int EM9118_DFROpen( char[] filePathName, int pathLen );

        int EM9118_DFRClose( long hDRF );

        int EM9118_DFRCodeBufferSize( long hDRF, int groupCount, IntByReference bufferSize );

        int EM9118_DFRReadCodeByGroupInx( long hDRF, byte[] codeBuf, int groupCodeCount, double codeBeginInx, IntByReference realReadCount );

        int EM9118_DFRAdChGetCode( long hDRF, int chInx, int bytesCount, ByteByReference originalCode, ShortByReference adCode, IntByReference adCodeCount );

        int EM9118_DFRAdCodeToValue( long hDRF, int chNo, short adCode, DoubleByReference adValue );

        int EM9118_DFRAdBatchCodeToValue( long hDRF, int chNo, short[] pCode, IntByReference codeCount, double[] adValue );

        int EM9118_DFRGetAdChValue( long hDRF, int chNo, char[] codeBuf, int groupCodeCount, double[] adValue );

        int EM9118_DFRCtChGetCode( long hDRF, int chInx, int bytesCount, byte[] originalCode, int[] ctCode, IntByReference ctCodeCount );

        int EM9118_DFRCtBatchCodeToValue( long hDRF, int chNo, int[] pCode, int codeCount, double[] ctValue );

        int EM9118_DFREcChGetCode( long hDRF, int chInx, int bytesCount, byte[] originalCode, int[] ctCode, IntByReference ctCodeCount );

        int EM9318_DFRIoGetCode( long hDRF, int bytesCount, byte[] originalCode, short[] ioCode, IntByReference ctCodeCount );

        int EM9118_DFRGetFreq( long hDRF, DoubleByReference daqFreq );

        int EM9118_DFRGetGroupTotal( long hDRF, DoubleByReference groupTotal );

        int EM9118_DFRGetAdIsInfifo( long hDRF, byte[] isInFifo );

        int EM9118_DFRGetCtIsInfifo( long hDRF, byte[] isInFifo );

        int EM9118_DFRGetEcIsInfifo( long hDRF, byte[] isInFifo );

        int EM9118_DFRGetClkSource( long hDRF, IntByReference clkSource );

        int EM9118_DFRGetEtrSource( long hDRF, IntByReference etrSource );

        int EM9118_OlFileOpen( byte[] filePathName );

        int EM9118_OlFileClose( long fileHandle );

        int EM9118_OlGetDataBytesCount( long fileHandle );

        int EM9118_OlGetAdEnCh( long fileHandle, byte[] enCh );

        int EM9118_OlGetCtEnCh( long fileHandle, byte[] enCh );

        int EM9118_OlGetEcEnCh( long fileHandle, byte[] enCh );

        int EM9118_OlGetGroupBytesCount( long fileHandle );

        int EM9118_OlGetGroupFreq( long fileHandle, DoubleByReference groupFreq );

        int EM9118_OlGetOriginalCode( long fileHandle, int readPos, int bytesCount, byte[] originalCode, IntByReference realBC );

        int EM9118_OlDirOpen( byte[] path );

        int EM9118_OlGetAdChCode( long fileHandle, int chInx, int bytesCount, byte[] originalCode, short[] adChCode, IntByReference adCodeCount );

        int EM9118_OlGetAdChValue( long fileHandle, int chInx, int bytesCount, byte[] originalCode, double[] adChValue, IntByReference adValueCount );

        int EM9118_OlGetCtChCode( long fileHandle, int chInx, int bytesCount, byte[] originalCode, int[] ctChCode, IntByReference ctCodeCount );

        int EM9118_OlGetCtChValue( long fileHandle, int chInx, int bytesCount, byte[] originalCode, double[] ctChValue, IntByReference ctValueCount );

        int EM9118_OlGetEcChCode( long fileHandle, int chInx, int bytesCount, byte[] originalCode, int[] ecChCode, IntByReference ecCodeCount );

        //////////////////////////////////和EM9106有关系的函数////////////////////////////////////////////////////
        int EM9106_IoSetDirAndMode( long hDevice, byte[] ioDir, byte[] doMode, int timeOutMS  );

        int EM9106_IoSetAll( long hDevice, byte[] oStatus, int timeOutMS  );

        int EM9106_IoGetAll( long hDevice, byte[] iStatus, int timeOutMS  );


//////////////////////////////////和EM9106有关系的函数////////////////////////////////////////////////////

        int EM9318_IoSetMode( long hDevice, int chNo, byte ioMode, int timeOutMS  );

        int EM9318_IoSetAll( long hDevice, byte[] oStatus, int timeOutMS  );

        int EM9318_IoGetAll( long hDevice, byte[] iStatus, int timeOutMS  );

        int EM9318_PwmStartAll( long hDevice, byte[] startOrStop, byte[] is90, int timeOutMS  );

        int EM9318_PwmSetPulse( long hDevice, int chNo, double freq, double dutyCycle, DoubleByReference realFreq, DoubleByReference realDutyCycle, int timeOutMS  );

        int EM9318_PwmIsOver( long hDevice, byte[] isOver, int timeOutMS  );

        int EM9318_PwmSetCount( long hDevice, int chNo, int setCount, int timeOutMS  );

        int EM9318_EcClear( long hDevice, int[] chClear, int timeOutMS  );


        int EM9318_EcReadCodeAll( long hDevice, int[] abCode, int timeOutMS  );

        int EM9118_DiIsInFifo( long hDevice, int isInFifo, int timeOutMS  );


        int EM9318_IoGetCode( long hDevice, int bytesCount, byte[] originalCode, short[] diCode, IntByReference diCodeCount );

        int EM9118_HcGetClientFifoStatus( long hDevice, IntByReference overTimes, IntByReference canReadByteCount, ByteByReference startMode, int timeOutMS  );

        int EM9118_GetConnectCount( long hDevice, ByteByReference cmdConnectCnt, ByteByReference dataConnectCnt, int timeOutMS  );

        int EM9118_CloseOthers( long hDevice, int timeOutMS  );


//////////////////////////////////UDP控制相关函数////////////////////////////////////////////////////
        int EM9118_UdpSetCmdPort( long hDevice, Pointer ptrIP, int ipBC, short udpPort, int cmdPort, int timeOutMS  );

        int EM9118_UdpSetDataPort( long hDevice, Pointer ptrIP, int ipBC, short udpPort, int dataPort, int timeOutMS  );

        int EM9118_UdpGetCmdPort( long hDevice, Pointer ptrIP, int ipBC, short udpPort, IntByReference cmdPort, int timeOutMS  );

        int EM9118_UdpGetDataPort( long hDevice, Pointer ptrIP, int ipBC, short udpPort, IntByReference dataPort, int timeOutMS  );

        int EM9118_Udp8004TestIP( long hDevice, Pointer ptrIP, int ipBC, int timeOutMS  );

        int EM9118_Udp8004Reboot( long hDevice, Pointer ptrIP, int ipBC, int timeOutMS  );

        int EM9118_SetWatchDog( long hDevice, short wtdTimeOutS , int timeOutMS  );

        int EM9118_ClearClientFifo( long hDevice, int timeOutMS  );


        //以下函数为定制产品使用，通用产品用户不建议使用
        int EM9118_Udp8004Execute( long hDev, Pointer ptrIP, int ipBC, ByteByReference cmd, int cmdBc, ByteByReference cmdRet, int retBc, int timeOutMS   );

        int EM9118_Udp8004RecvLogStart( long hDev, Pointer ptrIP, int ipBC, ByteByReference logName, int nameBc, short recvPort, int timeOutMS  );

        int EM9118_Udp8004GetRecvLogStatus( long hDev, IntByReference recvSize, IntByReference totalSize );

        int EM9118_Udp8004RecvLogStop( long hDev, int timeOutMS  );

//////////////////////////////////搜寻设备相关函数////////////////////////////////////////////////////
//以下函数为定制产品使用，通用产品用户不建议使用
        int EM9118_UdpCreate();

        void EM9118_UdpClose(long hDev);

        int EM9118_UdpDeviceSeekStart( long hDev, int ipInx );


        void EM9118_UdpDeviceSeekStop( long hDev);


        int EM9118_UdpDeviceIpFound( long hDev, int devInx, Pointer ptrIP, int strMaxLen );

        int EM9118_UdpDeviceIpAndVersion( long hDev, int ipInx, Pointer ptrIP, Pointer ptrVersion, int strMaxLen );

        int EM9118_UdpGetLocalNetInfo( long hDev, int ipInx, Pointer ptrIP, int strMaxLen );

        int EM9118_UdpSetDiAlarm( long hDevice, Pointer ptrIP, int ipBC, short udpPort, int diAlarmPort, byte diAlarmTV, int timeOutMS  );

    }
    //endregion

    //region 常量声明
    //定义常量
    public static final int EM9118_USB_MAX_COUNT = 16;           //最大可支持USB模块个数
    public static final double EM9118_BASE_FREQ = 36000000.0;       //基础时钟，M
    public static final double EM9118_PWM_BASE_FREQ = 4000000.0;	//PWM基准分频系数
    public static final int EM9118_MAXADCHCNT = 18;			//AD最大通道数
    public static final int EM9118_MAXDOCHCNT = 2;			//EM9118 DO最大通道数
    public static final int EM9118_MAXDICHCNT = 4;			//EM9118 DI最大通道数是路
    public static final int EM9118_MAXCTCHCNT = 4;			//计数器最大通道数
    public static final int EM9118_MAXECCHCNT = 2;			//编码器最大通道数
    public static final int EM9118_MAXPWMCHCNT = 2;			//PWM最大通道数
    public static final int EM9106_MAXADCHCNT = 6;			//AD最大通道数
    public static final int EM9106_MAXIOCHCNT = 24;			//EM9106的IO最大通道数
    public static final int EM9318_MAXIOCHCNT = 8;			//EM9318的IO最大通道数
    public static final int EM9318_MAXPWMCHCNT = 4;			//EM9318的PWM最大通道数
    public static final int EM9318_MAXECCHCNT = 2;			//EM9318的编码器最大通道数
    public static final double EM9318_PWM_BASE_FREQ = 36000000.0;			//EM9318的PWM时钟频率，36M

    //定义错误号
    public static final int EM9118_SUCCESS = 0;			//成功
    public static final int EM9118_FAILURE = -1;			//失败
    public static final int EM9118_TIMEOUT_ERROR = -2;			//超时错误
    public static final int EM9118_CONNECT_ERROR = -3;			//网络连接错误，发生此错误后应该重新建立连接
    public static final int EM9118_SEND_ERROR = -4;			//发送错误
    public static final int EM9118_CMDVERIFY_ERROR = -5;			//发送命令校验错误
    public static final int EM9118_RECVVERIFY_ERROR = -6;			//接收数据校验错误
    public static final int EM9118_DATANOTREADY = -7;			//数据没有准备好
    public static final int EM9118_PARA_ERROR = -8;			//参数错误
    public static final int EM9118_FREQBASE_ERROR = -9;			//参数错误
    public static final int EM9118_OTHER_ERROR = -10;			//其它错误，不同函数意义不同
    public static final int EM9118_THREAD_ERROR = -11;			//建立线程错误，一般在内存不够的时候才会发生
    public static final int EM9118_MEM_ERROR = -12;			//内存错误
    public static final int EM9118_RECV_ERROR = -13;			//接收错误
    public static final int EM9118_CLIENT_ERROR = -14;			//下位机不支持的命令
    public static final int EM9118_DATCONNECT_ERROR = -3;		//网络数据连接错误
    public static final int EM9118_NOCMD_ERROR = -20;			//下位机不支持的命令
    public static final int EM9118_NOPRIVILEGE_ERROR = -21;			//下位机没有操作权限
    public static final int EM9118_INITNET_ERROR = -100;			//初始化网络错误
    public static final int EM9118_SOCKET_ERROR = -101;			//打开网络套接字错误
    public static final int EM9118_FILEPATH_ERROR = -201;			//文件目录错误
    public static final int EM9118_FILEWRITE_ERROR = -202;			//写文件错误
    public static final int EM9118_FILEREAD_ERROR = -203;			//读文件错误
    public static final int EM9118_FILESEEK_ERROR = -204;			//文件定位错误
    public static final int EM9118_FILECLOSE_ERROR = -205;			//读文件错误

    //启动方式
    public static final int EM9118_CLKSRC_IN = 0;			//内时钟启动采集
    public static final int EM9118_CLKSRC_EX = 1;			//外时钟启动采集
    public static final int EM9118_TRISRC_IN = 0;			//内触发启动采集
    public static final int EM9118_TRISRC_EX = 1;			//外触发启动采集
    public static final int EM9118_TRI_EDGE = 0;			//外触发时边沿启动采集
    public static final int EM9118_TRI_LEVEL = 1;			//外触发时电平启动采集
    public static final int EM9118_TRI_UP = 0;			//外触发时上升沿（高电平）启动采集
    public static final int EM9118_TRI_DOWN = 1;			//外触发时下降沿（低电平）启动采集


    //AD采集范围
    public static final int EM9118_AD_RANGE_N10_10V = 0;			//±10V
    public static final int EM9118_AD_RANGE_N5_5V = 1;			//±5V
    public static final int EM9118_AD_RANGE_0_20MA = 2;			//0~20mA

    //计数方式
    public static final int EM9118_CT_MODE_COUNT = 0;			//计数
    public static final int EM9118_CT_MODE_HFREQ = 1;			//测高频
    public static final int EM9118_CT_MODE_LFREQ = 3;			//测低频

    //开关量输出管脚功能
    public static final int EM9118_DO_MODE_DO = 0;			//开关量输出
    public static final int EM9118_DO_MODE_PWM = 1;			//PWM
    public static final int EM9118_DO_MODE_OCLK = 2;			//OCLK，采集时钟输出
    //endregion

    //region 类变量声明
    public String strIP;                    //设备IP地址变量
    public int iCmdPort;                   //命令连接端口
    public int iDatPort;                   //数据连接端口
    public double dfFreq;                  //ad采集组频率
    private String strError;                //运行错误提示
    public int[] iIsAdInFifo;              //ad通道是否进fifo标识变量
    private int iGrpByteCnt;                //Fifo组字节数
    public int  iAdRangeIdx;                 //Ad范围取值下标
    public int  iClkSrc;                     //时钟源
    public int  iTriSrc;                     //触发源
    public int  iEdgeLevel;                  //触发方式
    public int  iUpdown;                     //
    public boolean      bAdType;            //返回的Ad类型，true——原码值，false——物理量值

    private int EM9118_TIMEOUT_MS = 1000;    //超时时间
    private int iReadTimeMS = 500;             //每次读取多少毫秒的采集数据，注意这个和采集频率有关，在低频状态下可能会有不符合预期的情况出现。
    public void SetReadTime( int iMS ) {
        if (iMS > 1000) {
            iReadTimeMS = 1000;
            EM9118_TIMEOUT_MS = 2000;
        } else if(iMS < 100){
            iReadTimeMS = 100;
            EM9118_TIMEOUT_MS = 1000;
        }else{
            iReadTimeMS = iMS;
            EM9118_TIMEOUT_MS = 1000;
        }
    }

    private long lIP;                       //IP地址变量的长度
    private Pointer ptrIP;                  //设备IP地址变量(需传入dll)
    private long hDev;                      //设备标识(需传入dll)

    private ThdSynchObj objSynVar;             //线程同步变量


    public int iAdChnInFifo=0;       //Fifo中Ad通道的数量
    public int iCtChnInFifo=0;       //Fifo中Ct通道的数量
    public int iEcChnInFifo=0;   //Fifo中Ec通道的数量
    public int iGroupCnt=0;        //每次读取数据组数
    public int iFrmByteCnt=0;    //每次读取字节数

    public double[][] df2AdValue;    //Ad显示值（可以是原码，也可以是物理值）
    public short[][]    i2AdCode;           //读回的Ad原码值
    public double[][]   df2AdVal;           //读回的Ad物理量值
    public double[][] df2CtValue;
    public double[][] df2EcValue;

    //endregion

    //region 类函数声明
    //构造器
    public Em9118()
    {
        strIP="192.168.1.128";
        hDev=IEm9118.INSTANCE.EM9118_DeviceCreate();
        dfFreq=4000.0;
        iGrpByteCnt=0;
        iAdRangeIdx=1;
        iClkSrc=0;
        iTriSrc=0;
        iEdgeLevel=1;
        iUpdown=0;
        iCmdPort=8000;
        iDatPort=8001;
        iIsAdInFifo=new int[EM9118_MAXADCHCNT];
        bAdType=true;
        int i;
        for(i=0;i<EM9118_MAXADCHCNT;i++)
        {
            iIsAdInFifo[i]=1;
        }
    }

    public Em9118(String str1)
    {
        strIP=str1;
        hDev=IEm9118.INSTANCE.EM9118_DeviceCreate();
        dfFreq=4000.0;
        iGrpByteCnt=0;
        iAdRangeIdx=1;
        iClkSrc=0;
        iTriSrc=0;
        iEdgeLevel=1;
        iUpdown=0;
        iCmdPort=8000;
        iDatPort=8001;
        iIsAdInFifo=new int[EM9118_MAXADCHCNT];
        bAdType=true;
        int i;
        for(i=0;i<EM9118_MAXADCHCNT;i++)
        {
            iIsAdInFifo[i]=1;
        }
        doShutDownWork();
    }

    //析构器
    @Override
    protected void finalize() throws Throwable {
        if( hDev != 0 )
            IEm9118.INSTANCE.EM9118_DeviceClose(hDev);
        hDev = 0;
    }
    private void doShutDownWork() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                if( hDev != 0 )
                    IEm9118.INSTANCE.EM9118_DeviceClose(hDev);
                hDev = 0;
            }
        });
    }
    //region 设备管理函数
    //连接设备的命令端口及数据端口
    public int DevConn()
    {
        int iRet=EM9118_SUCCESS;

        lIP=strIP.length();
        ptrIP=new Memory(lIP+10);

        ptrIP.setString(0,strIP,"US-ASCII");
        //byte[] cIP=strIP.getBytes(StandardCharsets.US_ASCII);
        iRet=IEm9118.INSTANCE.EM9118_CmdConnect(hDev,ptrIP,0,iCmdPort,EM9118_TIMEOUT_MS);

        if (iRet == EM9118_SUCCESS)
        {
            iRet=IEm9118.INSTANCE.EM9118_DataConnect(hDev,iDatPort,EM9118_TIMEOUT_MS);
            if(iRet!=EM9118_SUCCESS)
            {
                iRet=EM9118_DATCONNECT_ERROR;
            }
        }
        else
            iRet=EM9118_CONNECT_ERROR;


        return iRet;
    }

    //关闭设备的数据端口及命令端口
    public void DevDisConn()
    {
        IEm9118.INSTANCE.EM9118_DataClose(hDev,EM9118_TIMEOUT_MS);

        IEm9118.INSTANCE.EM9118_CmdClose(hDev,EM9118_TIMEOUT_MS);
    }
    //endregion

    //region 高速采集操作

    public void Malloc()
    {
        //获取每种测量值的通道数
        iAdChnInFifo = IEm9118.INSTANCE.EM9118_GetFifoAdChCount( hDev );
        iCtChnInFifo = IEm9118.INSTANCE.EM9118_GetFifoCtChCount( hDev );
        iEcChnInFifo = IEm9118.INSTANCE.EM9118_GetFifoEcChCount( hDev );

        //计算每通道数据量
        iGroupCnt = (int)dfFreq / (1000/iReadTimeMS);

        //给物理值分配空间
        df2AdValue=new double[iAdChnInFifo][iGroupCnt];

        //根据采集频率、每组字节数计算出半秒钟数据量
        iFrmByteCnt = iGrpByteCnt*iGroupCnt;
        //不应该出现这种情况：
        if( iFrmByteCnt == 0 || iGroupCnt == 0 )
        {
            iGroupCnt = 1;
            iFrmByteCnt = iGroupCnt;
        }
    }

    //启动高速采集
    public int StartHc()
    {
        int iRet=0;

        //设置AD组频率
        iRet= IEm9118.INSTANCE.EM9118_HcSetGroupFreq( hDev, dfFreq,EM9118_TIMEOUT_MS );
        if(iRet!=EM9118_SUCCESS)
        {
            return  iRet;
        }

        //设置ad通道是否进fifo
        iRet = IEm9118.INSTANCE.EM9118_AdChIsInFifo( hDev, iIsAdInFifo,EM9118_TIMEOUT_MS );
        if(iRet!=EM9118_SUCCESS)
        {
            return  iRet;
        }

        //得到组的字节数量
        IntByReference iGroupByteCount=new IntByReference(1);
        iRet = IEm9118.INSTANCE.EM9118_GetFifoGroupByteCount( hDev, iGroupByteCount );
        if(iRet!=EM9118_SUCCESS)
        {
            iGrpByteCnt=0;
            return iRet;
        }

        iGrpByteCnt=iGroupByteCount.getValue();

        //设置AD采集范围
        iRet = IEm9118.INSTANCE.EM9118_AdSetRange( hDev, iAdRangeIdx,EM9118_TIMEOUT_MS );
        if(iRet!=EM9118_SUCCESS)
        {
            return iRet;
        }

        //分配变量空间
        Malloc();

        //启动Daq
        iRet = IEm9118.INSTANCE.EM9118_HcStart( hDev, iClkSrc, iTriSrc, iEdgeLevel, iUpdown ,EM9118_TIMEOUT_MS);
        if(iRet!=EM9118_SUCCESS)
        {
        }

        df2AdVal=new double[EM9118_MAXADCHCNT][iGroupCnt];
        i2AdCode=new short[EM9118_MAXADCHCNT][iGroupCnt];

        return  iRet;
    }

    //停止高速采集
    public void StopHc()
    {
        int iRet=0;
        iRet = IEm9118.INSTANCE.EM9118_HcStop( hDev ,EM9118_TIMEOUT_MS);
        if(iRet!=EM9118_SUCCESS)
        {
        }
    }
    //endregion

    //region 数据操作

    //读取一次Fifo数据，并按照通道拆解数据。
    public double[][] ReadAdVal()  {
        int iRet=0;
        int i1=0;
        int i2=0;
        byte[] bcData;
        IntByReference ptrRead=new IntByReference(1);
        bcData=new byte[iFrmByteCnt];

        iRet = IEm9118.INSTANCE.EM9118_HcReadData( hDev, iFrmByteCnt, bcData , ptrRead,1000 );
        if(iRet!=EM9118_SUCCESS)
        {
        }

        //拆解数据
        short[] iAdCode=new short[iGroupCnt];
        IntByReference ptrAdCnt=new IntByReference(0);

        int iChnCount=df2AdVal.length>=iAdChnInFifo?iAdChnInFifo:df2AdVal.length;
        int iDataCount=i2AdCode[0].length>=iGroupCnt?iGroupCnt:i2AdCode[0].length;

        for(i1=0;i1<iChnCount;i1++) {
            iRet = IEm9118.INSTANCE.EM9118_AdChGetCode(hDev, i1, iFrmByteCnt, bcData, i2AdCode[i1], ptrAdCnt);
            if (iRet != EM9118_SUCCESS) {
            }
        }

        if(bAdType)
        {
            int iLen2;
            for(i1=0;i1<iChnCount;i1++) {
                iLen2=i2AdCode[i1].length>=iGroupCnt?iGroupCnt:i2AdCode[i1].length;
                for(i2=0;i2<iLen2;i2++)
                {
                    df2AdVal[i1][i2]=i2AdCode[i1][i2];
                }

            }
        }
        else {
            //AD原码值转化成物理值，注意这里默认起始通道为1，且终止通道和起始通道之间都连续允许进FIFO
            for(i1=0;i1<iChnCount;i1++)
            {
                iRet=IEm9118.INSTANCE.EM9118_AdChBatchCodeToValue( hDev, i1 + 1, i2AdCode[i1], iDataCount, df2AdVal[i1] );
                if(iRet==EM9118_SUCCESS)
                {

                }
                else {
                    System.out.println("Ad Batch code failure!");
                }
            }

        }

        return  df2AdVal;
    }
    //endregion
    //endregion






}
